#include <iostream>
#include <vector>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include "bglProgram.h"
#include "bglTexture2D.h"
#include "bglCamera.h"
#include "bglWidget.h"

#include "box.hpp"

class BaseWidget : public BGLWidget
{
private:
	BGLCamera m_camera;

	bool m_leftIsPress; //判断鼠标左键是否按下
	float m_lastX;   //上一帧鼠标的x位置
	float m_lastY;   //上一帧鼠标的y位置

	std::vector<Box*> m_boxs;

public:
	BaseWidget() : BGLWidget()
	{
		m_leftIsPress = false;
	}

	~BaseWidget()
	{
		for (size_t i = 0; i < m_boxs.size(); i++)
		{
			delete m_boxs[i];
		}
	}

	virtual void Init() 
	{
		int screenWidth;
		int screenHeight;
		this->GetWindowSize(&screenWidth, &screenHeight);
		m_camera.InitCamera(screenWidth, screenHeight);

		Box* m_box0 = new Box;
		m_box0->SetCanera(&m_camera);
		m_box0->SetScale(glm::vec3(10, 10, 0.01));
		m_boxs.push_back(m_box0);

		Box* m_box1 = new Box;
		m_box1->SetCanera(&m_camera);
		m_box1->SetTexture("./data/images/face.png");
		m_boxs.push_back(m_box1);	
	}

	virtual void Render()
	{
		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		glm::vec3 cubePositions[] = {
			glm::vec3( 0.0f,  0.0f,  0.0f), 
			glm::vec3( 2.0f,  5.0f, -15.0f), 
			glm::vec3(-1.5f, -2.2f, -2.5f),  
			glm::vec3(-3.8f, -2.0f, -12.3f),  
			glm::vec3( 2.4f, -0.4f, -3.5f),  
			glm::vec3(-1.7f,  3.0f, -7.5f),  
			glm::vec3( 1.3f, -2.0f, -2.5f),  
			glm::vec3( 1.5f,  2.0f, -2.5f), 
			glm::vec3( 1.5f,  0.2f, -1.5f), 
			glm::vec3(-1.3f,  1.0f, -1.5f)  
		};

		for (size_t i = 0; i < m_boxs.size(); i++)
		{
			m_boxs[i]->Begin();

			m_boxs[i]->SetPosition(cubePositions[i]);

			m_boxs[i]->End();
		}
	}

	virtual void FramebufferSizeCallback(GLFWwindow* window, int width, int height)
	{
		if(width != 0 && height != 0)
		{
			glViewport(0, 0, width, height);
			m_camera.SetScreenWidth(width);
			m_camera.SetScreenHeight(height);
		}
	}

	virtual void ScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
	{
		glm::vec3 position = m_camera.GetPosition();

		std::cout << yoffset << std::endl;

		if (yoffset > 0)
			position.z *= 0.8f;
		else
			position.z *= 1.2f;

		m_camera.SetPosition(position);
	}

	virtual void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
	{
		glm::vec3 target = m_camera.GetTargetPosition();

		if (key == GLFW_KEY_W && (action == GLFW_REPEAT || action == GLFW_PRESS))
		{
			target.y -= 0.2f;
		}	
		if (key == GLFW_KEY_S && (action == GLFW_REPEAT || action == GLFW_PRESS))
		{
			target.y += 0.2f;
		}
			
		if (key == GLFW_KEY_A && (action == GLFW_REPEAT || action == GLFW_PRESS))
		{
			target.x += 0.2f;
		}
			
		if (key == GLFW_KEY_D && (action == GLFW_REPEAT || action == GLFW_PRESS))
		{
			target.x -= 0.2f;
		}
			
		m_camera.SetTargetPosition(target);
	}

	virtual void MousebuttonCallback(GLFWwindow* window, int button, int action, int mods)
	{
		if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
		{
			m_leftIsPress = true;
		}
		if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE)
		{
			m_leftIsPress = false;
		}
	}

	virtual void CursorPositionCallback(GLFWwindow * window, double xpos, double ypos)
	{
		if (m_leftIsPress)
		{
			float offsetX = xpos - m_lastX;
			float offsetY = ypos - m_lastY;

			glm::vec3 rotate(offsetY, offsetX, 0);
			m_camera.RotationOfWorld(rotate);
		}

		m_lastX = xpos;
		m_lastY = ypos;	
	}
}; 



int main() {
	
	BaseWidget widget;
	widget.Run();

	return 0;
}